//
// Created by lixiaoqi on 2024-01-26.
//
#include "ThreadPool.hpp"

using namespace std;
void Thread::Start() {
    thread th(func, threadId);
    th.detach();
}

Thread::Thread(ThreadCB func, int id): func(func), threadId(id) {}

// ------------------------------------
void ThreadPool::Start(unsigned int size) {
    this->initSize = size;
    for (int i = 0; i < size; ++i) {
        auto func = bind(&ThreadPool::ThreadTask, this, std::placeholders::_1);
        auto ptr = make_unique<Thread>(func);
        threads.push_back(std::move(ptr));
    }
    this->isRunning = true;
    this->curThreadSize += size;
    for (auto& thread: threads) {
        thread->Start();
    }
}
void ThreadPool::ResetMode(PoolMode mode) {
    // 只有在线程池没有运行的时候才能修改模式
    if (isRunning) {
        return;
    }
    this->mode = mode;
}
ThreadPool::~ThreadPool() {
    this->isRunning = false;
    notEmpty.notify_all();
    notFull.notify_all();
    // 阻塞等待所有的线程退出
    unique_lock<mutex> lock(mtx);
    // 当前所有存活的线程为0时，我们就可以退出了
    exitCon.wait(lock, [this]()->bool {return !curThreadSize;});
}
void ThreadPool::ThreadTask(int threadId) {
    using namespace this_thread;
    auto lastTime = std::chrono::high_resolution_clock::now();
    // 取出任务进行执行
    while(isRunning) {
        unique_lock<mutex> lock(mtx);
        idleThreadSize--;
        while(isRunning && taskSize == 0) {
            // 在cached模式下，线程数量过多，等待状态下超过六十秒，我们要进行回收
            if (mode == PoolMode::cached && curThreadSize > initSize && idleThreadSize ) {
                // 每次返回，都要判断是不是超时返回的
                auto res = notEmpty.wait_for(lock, chrono::seconds(1));
                // 超时返回的，我们就要进行回收
                auto now = chrono::high_resolution_clock::now();
                auto duration = chrono::duration_cast<chrono::seconds>(now - lastTime);
                if (res == cv_status::timeout && duration.count() >= 3) {
                    // 根据threadId 清理掉对应的线程
                    cout << "delete thread" << endl;
                    this->DeleteThread(threadId);
                    return;
                }
            } else {
                notEmpty.wait(lock);
            }
        }
        // 线程池结束后，退出循环，通知结束
        if (!isRunning) {
            break;
        }
        auto task = tasks.front();
        tasks.pop();
        taskSize--;
        if (taskSize > 0) {
            notEmpty.notify_one();
        }

        lock.unlock();
        notFull.notify_one();
        // 任务执行完完毕后，将结果放入到result中
        task();
        idleThreadSize++;
        lastTime = std::chrono::high_resolution_clock::now();
    }
    if (!isRunning) {
        DeleteThread(threadId);
        cout << "thread "<< this_thread::get_id() << " exit" << endl;
        exitCon.notify_all();
    }
}
void ThreadPool::AddThread() {
    auto func = bind(&ThreadPool::ThreadTask, this, std::placeholders::_1);
    auto ptr = make_unique<Thread>(func);
    ptr->Start();
    threads.push_back(std::move(ptr));
    curThreadSize++;
}
void ThreadPool::DeleteThread(int threadId) {
    auto thread = find_if(threads.begin(), threads.end(),
                          [threadId](auto& thread)->bool {
                              return thread->getThreadId() == threadId;
                          });
    if (thread != threads.end()) {
        threads.erase(thread);
        curThreadSize--;
        idleThreadSize--;
    }
}

ThreadPool::ThreadPool() {

}
